using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using Matrix.Notification.Domain.Shared.Notifications;

namespace Matrix.Notification.Domain.Notifications
{
    /// <summary>
    /// 通知聚合根实体
    /// </summary>
    public class Notification : FullAuditedAggregateRoot<Guid>, IMultiTenant
    {
        /// <summary>
        /// 租户ID
        /// </summary>
        public virtual Guid? TenantId { get; protected set; }

        /// <summary>
        /// 通知标题
        /// </summary>
        public virtual string Title { get; protected set; } = string.Empty;

        /// <summary>
        /// 通知内容
        /// </summary>
        public virtual string Content { get; protected set; } = string.Empty;

        /// <summary>
        /// 通知类型
        /// </summary>
        public virtual NotificationType Type { get; protected set; }

        /// <summary>
        /// 通知优先级
        /// </summary>
        public virtual NotificationPriority Priority { get; protected set; }

        /// <summary>
        /// 通知状态
        /// </summary>
        public virtual NotificationStatus Status { get; protected set; }

        /// <summary>
        /// 接收者ID
        /// </summary>
        public virtual Guid? RecipientId { get; protected set; }

        /// <summary>
        /// 接收者用户名
        /// </summary>
        public virtual string? RecipientUserName { get; protected set; }

        /// <summary>
        /// 接收者邮箱
        /// </summary>
        public virtual string? RecipientEmail { get; protected set; }

        /// <summary>
        /// 接收者手机号
        /// </summary>
        public virtual string? RecipientPhoneNumber { get; protected set; }

        /// <summary>
        /// 发送者ID
        /// </summary>
        public virtual Guid? SenderId { get; protected set; }

        /// <summary>
        /// 发送者姓名
        /// </summary>
        public virtual string? SenderName { get; protected set; }

        /// <summary>
        /// 通知渠道
        /// </summary>
        public virtual NotificationChannel Channel { get; protected set; }

        /// <summary>
        /// 模板ID
        /// </summary>
        public virtual Guid? TemplateId { get; protected set; }

        /// <summary>
        /// 模板名称
        /// </summary>
        public virtual string? TemplateName { get; protected set; }

        /// <summary>
        /// 通知参数（JSON格式）
        /// </summary>
        public virtual string? Parameters { get; protected set; }

        /// <summary>
        /// 附件列表（JSON格式）
        /// </summary>
        public virtual string? Attachments { get; protected set; }

        /// <summary>
        /// 调度时间
        /// </summary>
        public virtual DateTime? ScheduledTime { get; protected set; }

        /// <summary>
        /// 过期时间
        /// </summary>
        public virtual DateTime? ExpirationTime { get; protected set; }

        /// <summary>
        /// 重试次数
        /// </summary>
        public virtual int RetryCount { get; protected set; }

        /// <summary>
        /// 最大重试次数
        /// </summary>
        public virtual int MaxRetryCount { get; protected set; }

        /// <summary>
        /// 下次重试时间
        /// </summary>
        public virtual DateTime? NextRetryTime { get; protected set; }

        /// <summary>
        /// 发送时间
        /// </summary>
        public virtual DateTime? SentTime { get; protected set; }

        /// <summary>
        /// 送达时间
        /// </summary>
        public virtual DateTime? DeliveredTime { get; protected set; }

        /// <summary>
        /// 阅读时间
        /// </summary>
        public virtual DateTime? ReadTime { get; protected set; }

        /// <summary>
        /// 失败原因
        /// </summary>
        public virtual string? FailureReason { get; protected set; }

        /// <summary>
        /// 外部ID（用于与外部系统集成）
        /// </summary>
        public virtual string? ExternalId { get; protected set; }

        /// <summary>
        /// 批次ID（批量发送时使用）
        /// </summary>
        public virtual Guid? BatchId { get; protected set; }

        /// <summary>
        /// 分类标签
        /// </summary>
        public virtual string? Category { get; protected set; }

        /// <summary>
        /// 业务数据（JSON格式）
        /// </summary>
        public virtual string? BusinessData { get; protected set; }

        /// <summary>
        /// 是否静默发送
        /// </summary>
        public virtual bool IsSilent { get; protected set; }

        /// <summary>
        /// 是否需要确认
        /// </summary>
        public virtual bool RequiresConfirmation { get; protected set; }

        /// <summary>
        /// 确认截止时间
        /// </summary>
        public virtual DateTime? ConfirmationDeadline { get; protected set; }

        /// <summary>
        /// 是否已确认
        /// </summary>
        public virtual bool IsConfirmed { get; protected set; }

        /// <summary>
        /// 确认时间
        /// </summary>
        public virtual DateTime? ConfirmedTime { get; protected set; }

        /// <summary>
        /// 地理位置限制
        /// </summary>
        public virtual string? LocationRestriction { get; protected set; }

        /// <summary>
        /// 时间限制
        /// </summary>
        public virtual string? TimeRestriction { get; protected set; }

        /// <summary>
        /// 设备限制
        /// </summary>
        public virtual string? DeviceRestriction { get; protected set; }

        /// <summary>
        /// 通知编码
        /// </summary>
        public virtual string NotificationCode { get; protected set; } = string.Empty;

        /// <summary>
        /// 关联ID
        /// </summary>
        public virtual Guid? RelatedEntityId { get; protected set; }

        /// <summary>
        /// 关联类型
        /// </summary>
        public virtual string? RelatedEntityType { get; protected set; }

        /// <summary>
        /// 是否已归档
        /// </summary>
        public virtual bool IsArchived { get; protected set; }

        /// <summary>
        /// 归档时间
        /// </summary>
        public virtual DateTime? ArchivedTime { get; protected set; }

        protected Notification()
        {
        }

        /// <summary>
        /// 创建新通知
        /// </summary>
        public Notification(
            Guid id,
            Guid? tenantId,
            string title,
            string content,
            NotificationType type,
            NotificationPriority priority,
            NotificationChannel channel,
            Guid? recipientId = null,
            string? recipientUserName = null,
            string? recipientEmail = null,
            string? recipientPhoneNumber = null,
            Guid? senderId = null,
            string? senderName = null)
            : base(id)
        {
            TenantId = tenantId;
            Title = Check.NotNullOrWhiteSpace(title, nameof(title), maxLength: 500);
            Content = Check.NotNullOrWhiteSpace(content, nameof(content), maxLength: 4000);
            Type = type;
            Priority = priority;
            Channel = channel;
            Status = NotificationStatus.Pending;
            RecipientId = recipientId;
            RecipientUserName = recipientUserName;
            RecipientEmail = recipientEmail;
            RecipientPhoneNumber = recipientPhoneNumber;
            SenderId = senderId;
            SenderName = senderName;
            MaxRetryCount = 3;
            IsSilent = false;
            RequiresConfirmation = false;
            IsConfirmed = false;
            IsArchived = false;
            NotificationCode = GenerateNotificationCode();
        }

        /// <summary>
        /// 更新通知内容
        /// </summary>
        public virtual Notification UpdateContent(string title, string content)
        {
            if (Status != NotificationStatus.Draft && Status != NotificationStatus.Pending)
            {
                throw new UserFriendlyException("只能修改草稿或待发送状态的通知");
            }

            Title = Check.NotNullOrWhiteSpace(title, nameof(title), maxLength: 500);
            Content = Check.NotNullOrWhiteSpace(content, nameof(content), maxLength: 4000);
            return this;
        }

        /// <summary>
        /// 更新接收者信息
        /// </summary>
        public virtual Notification UpdateRecipient(
            Guid? recipientId = null,
            string? recipientUserName = null,
            string? recipientEmail = null,
            string? recipientPhoneNumber = null)
        {
            if (Status != NotificationStatus.Draft && Status != NotificationStatus.Pending)
            {
                throw new UserFriendlyException("只能修改草稿或待发送状态的通知");
            }

            RecipientId = recipientId;
            RecipientUserName = recipientUserName;
            RecipientEmail = recipientEmail;
            RecipientPhoneNumber = recipientPhoneNumber;
            return this;
        }

        /// <summary>
        /// 设置调度时间
        /// </summary>
        public virtual Notification Schedule(DateTime scheduledTime)
        {
            if (Status != NotificationStatus.Draft && Status != NotificationStatus.Pending)
            {
                throw new UserFriendlyException("只能调度草稿或待发送状态的通知");
            }

            ScheduledTime = scheduledTime;
            Status = NotificationStatus.Scheduled;
            return this;
        }

        /// <summary>
        /// 开始发送
        /// </summary>
        public virtual Notification StartSending()
        {
            if (Status != NotificationStatus.Pending && Status != NotificationStatus.Scheduled && Status != NotificationStatus.Retrying)
            {
                throw new UserFriendlyException("只能发送待发送、已调度或重试中的通知");
            }

            Status = NotificationStatus.Sending;
            SentTime = DateTime.UtcNow;
            return this;
        }

        /// <summary>
        /// 标记为已发送
        /// </summary>
        public virtual Notification MarkAsSent(string? externalId = null)
        {
            if (Status != NotificationStatus.Sending)
            {
                throw new UserFriendlyException("只能标记发送中的通知为已发送");
            }

            Status = NotificationStatus.Sent;
            DeliveredTime = DateTime.UtcNow;
            ExternalId = externalId;
            return this;
        }

        /// <summary>
        /// 标记为已送达
        /// </summary>
        public virtual Notification MarkAsDelivered()
        {
            if (Status != NotificationStatus.Sent)
            {
                throw new UserFriendlyException("只能标记已发送的通知为已送达");
            }

            Status = NotificationStatus.Delivered;
            DeliveredTime = DateTime.UtcNow;
            return this;
        }

        /// <summary>
        /// 标记为已读
        /// </summary>
        public virtual Notification MarkAsRead()
        {
            if (Status != NotificationStatus.Delivered)
            {
                throw new UserFriendlyException("只能标记已送达的通知为已读");
            }

            Status = NotificationStatus.Read;
            ReadTime = DateTime.UtcNow;
            return this;
        }

        /// <summary>
        /// 标记为发送失败
        /// </summary>
        public virtual Notification MarkAsFailed(string failureReason)
        {
            if (Status != NotificationStatus.Sending && Status != NotificationStatus.Sent)
            {
                throw new UserFriendlyException("只能标记发送中或已发送的通知为失败");
            }

            Status = NotificationStatus.Failed;
            FailureReason = failureReason;
            RetryCount++;

            // 如果还能重试，设置重试状态
            if (RetryCount < MaxRetryCount)
            {
                Status = NotificationStatus.Retrying;
                NextRetryTime = CalculateNextRetryTime();
            }

            return this;
        }

        /// <summary>
        /// 标记为已取消
        /// </summary>
        public virtual Notification Cancel(string? reason = null)
        {
            if (Status == NotificationStatus.Sent || Status == NotificationStatus.Delivered || Status == NotificationStatus.Read)
            {
                throw new UserFriendlyException("无法取消已发送或已送达的通知");
            }

            Status = NotificationStatus.Cancelled;
            FailureReason = reason;
            return this;
        }

        /// <summary>
        /// 标记为已过期
        /// </summary>
        public virtual Notification MarkAsExpired()
        {
            if (Status == NotificationStatus.Expired)
            {
                return this;
            }

            Status = NotificationStatus.Expired;
            FailureReason = "通知已过期";
            return this;
        }

        /// <summary>
        /// 确认通知
        /// </summary>
        public virtual Notification Confirm()
        {
            if (!RequiresConfirmation)
            {
                throw new UserFriendlyException("该通知不需要确认");
            }

            if (IsConfirmed)
            {
                return this;
            }

            if (ConfirmationDeadline.HasValue && DateTime.UtcNow > ConfirmationDeadline.Value)
            {
                throw new UserFriendlyException("已超过确认截止时间");
            }

            IsConfirmed = true;
            ConfirmedTime = DateTime.UtcNow;
            return this;
        }

        /// <summary>
        /// 归档通知
        /// </summary>
        public virtual Notification Archive()
        {
            if (IsArchived)
            {
                return this;
            }

            IsArchived = true;
            ArchivedTime = DateTime.UtcNow;
            return this;
        }

        /// <summary>
        /// 设置模板信息
        /// </summary>
        public virtual Notification SetTemplate(Guid templateId, string templateName, string? parameters = null)
        {
            if (Status != NotificationStatus.Draft && Status != NotificationStatus.Pending)
            {
                throw new UserFriendlyException("只能为草稿或待发送状态的通知设置模板");
            }

            TemplateId = templateId;
            TemplateName = templateName;
            Parameters = parameters;
            return this;
        }

        /// <summary>
        /// 设置附件
        /// </summary>
        public virtual Notification SetAttachments(string attachments)
        {
            if (Status != NotificationStatus.Draft && Status != NotificationStatus.Pending)
            {
                throw new UserFriendlyException("只能为草稿或待发送状态的通知设置附件");
            }

            Attachments = attachments;
            return this;
        }

        /// <summary>
        /// 设置业务数据
        /// </summary>
        public virtual Notification SetBusinessData(string businessData)
        {
            BusinessData = businessData;
            return this;
        }

        /// <summary>
        /// 设置关联实体信息
        /// </summary>
        public virtual Notification SetRelatedEntity(Guid? entityId, string? entityType)
        {
            RelatedEntityId = entityId;
            RelatedEntityType = entityType;
            return this;
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        public virtual Notification SetExpirationTime(DateTime expirationTime)
        {
            ExpirationTime = expirationTime;
            return this;
        }

        /// <summary>
        /// 设置静默模式
        /// </summary>
        public virtual Notification SetSilent(bool isSilent)
        {
            IsSilent = isSilent;
            return this;
        }

        /// <summary>
        /// 设置确认要求
        /// </summary>
        public virtual Notification SetConfirmation(bool requiresConfirmation, DateTime? confirmationDeadline = null)
        {
            RequiresConfirmation = requiresConfirmation;
            ConfirmationDeadline = confirmationDeadline;
            return this;
        }

        /// <summary>
        /// 设置批次ID
        /// </summary>
        public virtual Notification SetBatchId(Guid batchId)
        {
            BatchId = batchId;
            return this;
        }

        /// <summary>
        /// 设置分类标签
        /// </summary>
        public virtual Notification SetCategory(string category)
        {
            Category = category;
            return this;
        }

        /// <summary>
        /// 设置限制条件
        /// </summary>
        public virtual Notification SetRestrictions(
            string? locationRestriction = null,
            string? timeRestriction = null,
            string? deviceRestriction = null)
        {
            LocationRestriction = locationRestriction;
            TimeRestriction = timeRestriction;
            DeviceRestriction = deviceRestriction;
            return this;
        }

        /// <summary>
        /// 重置重试状态
        /// </summary>
        public virtual Notification ResetRetry()
        {
            RetryCount = 0;
            NextRetryTime = null;
            if (Status == NotificationStatus.Failed)
            {
                Status = NotificationStatus.Pending;
            }
            return this;
        }

        /// <summary>
        /// 检查是否可以重试
        /// </summary>
        public virtual bool CanRetry()
        {
            return Status == NotificationStatus.Failed && RetryCount < MaxRetryCount;
        }

        /// <summary>
        /// 检查是否已过期
        /// </summary>
        public virtual bool IsExpired()
        {
            return ExpirationTime.HasValue && DateTime.UtcNow > ExpirationTime.Value;
        }

        /// <summary>
        /// 检查是否已过确认截止时间
        /// </summary>
        public virtual bool IsConfirmationDeadlinePassed()
        {
            return RequiresConfirmation &&
                   ConfirmationDeadline.HasValue &&
                   DateTime.UtcNow > ConfirmationDeadline.Value &&
                   !IsConfirmed;
        }

        /// <summary>
        /// 生成通知编码
        /// </summary>
        protected virtual string GenerateNotificationCode()
        {
            return $"NOT_{DateTime.UtcNow:yyyyMMdd}_{Guid.NewGuid().ToString("N")[..8].ToUpper()}";
        }

        /// <summary>
        /// 计算下次重试时间
        /// </summary>
        protected virtual DateTime? CalculateNextRetryTime()
        {
            if (RetryCount >= MaxRetryCount)
            {
                return null;
            }

            // 指数退避策略：2^retryCount * 60秒，最大不超过1小时
            var delayMinutes = Math.Min(Math.Pow(2, RetryCount) * 1, 60);
            return DateTime.UtcNow.AddMinutes(delayMinutes);
        }
    }
}